#ifndef GAMEKIT_SAFEPOINTER_H
#define GAMEKIT_SAFEPOINTER_H

#include "../gamekit.h"

namespace gamekit
{
	template<typename T>
	class GK_API SafePointer
	{
	public:
		SafePointer();
		SafePointer(T* t);
		SafePointer(const SafePointer& p);

		~SafePointer();

		SafePointer& operator=(const SafePointer& other);
		SafePointer& operator=(T* t);

		T* operator->() const;
		
		operator bool() const;
		bool operator !() const;

		inline friend bool operator==(const SafePointer<T>& sp, const T* t)
		{
			return sp.m_t == t;
		}

		inline friend bool operator==(const T* t, const SafePointer<T>& sp)
		{
			return t == sp.m_t;
		}

		inline friend bool operator!=(const SafePointer<T>& sp, const T* t)
		{
			return sp.m_t != t;
		}

		inline friend bool operator!=(const T* t, const SafePointer<T>& sp)
		{
			return t != sp.m_t;
		}

		template<typename U>
		inline friend bool operator==(const SafePointer<T>& sp, const U* t)
		{
			return sp.m_t == t;
		}

		template<typename U>
		inline friend bool operator!=(const U* t, const SafePointer<T>& sp)
		{
			return t != sp.m_t;
		}

		template<typename U>
		inline friend bool operator==(const SafePointer<T>& sp, const SafePointer<U>& su)
		{
			return sp.m_t == su.m_t;
		}

		template<typename U>
		inline friend bool operator!=(const SafePointer<U>& su, const SafePointer<T>& sp)
		{
			return su.m_t != sp.m_t;
		}
	private:
		T* m_t;
	};

	template<typename T>
	SafePointer<T>::SafePointer()
		: m_t(NULL)
	{
	}

	template<typename T>
	SafePointer<T>::SafePointer(const SafePointer& p)
		: m_t(p.m_t)
	{
	}

	template<typename T>
	SafePointer<T>::SafePointer(T* t)
		: m_t(t)
	{
	}

	template<typename T>
	SafePointer<T>::~SafePointer()
	{
	}

	template<typename T>
	SafePointer<T>& SafePointer<T>::operator=(const SafePointer<T>& other)
	{
		m_t = other.m_t;
		return *this;
	}

	template<typename T>
	SafePointer<T>& SafePointer<T>::operator=(T* t)
	{
		m_t = t;
		return *this;
	}

	template<typename T>
	T* SafePointer<T>::operator->() const
	{
		return m_t;
	}

	template<typename T>
	SafePointer<T>::operator bool() const
	{
		return m_t != NULL;
	}

	template<typename T>
	bool SafePointer<T>::operator !() const
	{
		return m_t == NULL;
	}
}

#endif